package com.atguigu.juc.atomics;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * 以一种线程安全的方式操作非线程安全对象的某些字段
 *
 * <p>需求：10个线程，每个线程向一个账号转账1000，不使用synchronized,尝试使用AtomicIntegerFieldUpdater来实现
 *
 * <p>使用要求：
 * <p>1、更新的对象属性必须使用 public volatile 修饰符
 * <p>2、因为对象的属性修改类型原子类都是抽象类，所以每次使用都必须使用静态方法newUpdater()创建一个更新器，并且需要设置想要更新的类和属性
 *
 * @author yfstart
 * @create 2022-07-21 1:47
 */
public class AtomicIntegerFieldUpdaterDemo {
  public static void main(String[] args) throws InterruptedException {
    BankAccount bankAccount = new BankAccount();
    CountDownLatch countDownLatch = new CountDownLatch(10);

    for (int i = 0; i < 10; i++) {
      new Thread(() -> {
        try {
          for (int j = 0; j < 1000; j++) {
            // bankAccount.add();
            bankAccount.transMoney(bankAccount);
          }
        } finally {
          countDownLatch.countDown();
        }
      }, String.valueOf(i)).start();
    }

    countDownLatch.await();
    System.out.println(Thread.currentThread().getName() + "\t 账户余额：" + bankAccount.money);
  }
}

class BankAccount {
  String bankName = "CCB";
  // 1、更新的对象属性必须使用 public volatile 修饰符
  public volatile int money = 0;
  // 2、因为对象的属性修改类型原子类都是抽象类，所以每次使用都必须使用静态方法newUpdater()创建一个更新器，并且需要设置想要更新的类和属性
  AtomicIntegerFieldUpdater fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class, "money");

  public void add() {
    money++;
  }

  // 不使用 synchronized，保证高性能原子性，局部微创小手术
  public void transMoney(BankAccount bankAccount) {
    fieldUpdater.getAndIncrement(bankAccount);
  }
}
